﻿#pragma once

#include <learn/topo/topo.h>

namespace xi
{

namespace topo
{

class Topo_Face : public Topo_Shape
{
    friend class Topo_Builder;
    friend class Topo_Explorer;

  protected:
    /**
     * @brief 空构造
     *
     */
    Topo_Face();

    /**
     * @brief 删除所有赋值和拷贝构造函数
     *
     */
    Topo_Face(Topo_Face &&) = delete;

    /**
     * @brief 析构
     *
     */
    ~Topo_Face();

  public:
    /**
     * @brief 第一条 wire
     *
     * @return Topo_Wire*&
     */
    Topo_Wire *&wire();

    /**
     * @brief 添加属性
     *
     * @tparam T
     * @param[in] prop
     */
    template <typename T> void add_property(const FProperty_Handle<T> &prop)
    {
        if (m_properties == nullptr)
            m_properties.reset(new Topo_Prop);

        // 注意创建一个新的属性，否则会有生命周期问题
        ASSERT_INFO(!has_property(prop), "Property already exists");
        m_properties->prop.push_back(new FProperty_Handle<T>(prop.name()));
    }

    /**
     * @brief 属性操作
     *
     * @tparam T
     * @param[in] handle
     * @return T&
     */
    template <typename T> T &property(const FProperty_Handle<T> &handle)
    {
        ASSERT_INFO(m_properties != nullptr, "Property not found");

        auto name = handle.name();
        auto it = std::find_if(m_properties->prop.begin(), m_properties->prop.end(),
                               [&](Property_Base *val) { return val->name() == name; });

        FProperty_Handle<T> *prop = nullptr;
        ASSERT_INFO(it != m_properties->prop.end(), "Property not found");
        prop = static_cast<FProperty_Handle<T> *>(*it);

        // 因为创建的时候已经初始化了，所以一定能找到
        return prop->property();
    }

  protected:
    Topo_Wire *m_wire; // 面上的第一条 wire，即最初的逆时针内环，通过链表形式连接
};

} // namespace topo

} // namespace xi
